﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleAppDemo {
    class Program {
        static void Main(string[] args)
        {
            #region 测试入口

            MREMethod();

            #endregion

            Console.ReadKey();
        }

        #region volatile用法
        static void WorkerThreadExample()
        {
            Worker workerObject = new Worker();
            Thread workerThread = new Thread(workerObject.DoWork);
            workerThread.Start();
            Console.WriteLine("Main thread:starting worker thread...");
            while (!workerThread.IsAlive) ;
            Thread.Sleep(1);
            workerObject.RequestStop();
            workerThread.Join();
            Console.WriteLine("Main thread:worker thread has terminated.");
        }
        #endregion

        #region ReaderWriterLockSlim和Lock锁性能比较

        static void RwLockSlim()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            List<Task> lstTask = new List<Task>();
            for (int i = 0; i < 500; i++)
            {
                if (i % 25 != 0)
                {
                    var t = Task.Factory.StartNew(RwLock.ReadSomething);
                    lstTask.Add(t);
                }
                else
                {
                    var t = Task.Factory.StartNew(RwLock.WriteSomething);
                    lstTask.Add(t);
                }
            }
            Task.WaitAll(lstTask.ToArray());
            sw.Stop();
            Console.WriteLine("使用ReaderWriterSlim方式，耗时：" + sw.Elapsed);
            sw.Restart();

            lstTask = new List<Task>();
            for (int i = 0; i < 500; i++)
            {
                if (i % 25 != 0)
                {
                    var t = Task.Factory.StartNew(RwNormalLock.ReadSomething_lock);
                    lstTask.Add(t);
                }
                else
                {
                    var t = Task.Factory.StartNew(RwNormalLock.WriteSomething_lock);
                    lstTask.Add(t);
                }
            }
            Task.WaitAll(lstTask.ToArray());
            sw.Stop();
            Console.WriteLine("使用lock方式，耗时：" + sw.Elapsed);
        }

        #endregion

        #region 多个线程同时写入同一个文件将会导致错误
        static int LogCount = 100;
        static void NormalFileWrite()
        {
            Parallel.For(0, LogCount, e =>
            {
                FileManage.WriteFileLog();
            });
            Console.WriteLine(string.Format("\r\nLog Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.",
                LogCount.ToString(),
                FileManage.WritedCount.ToString(),
                FileManage.FailedCount.ToString()));
        }
        static void RwLockSlimFileWrite()
        {
            Parallel.For(0, LogCount, e =>
            {
                FileRwLockManage.RwriteLog();
            });
            Console.WriteLine(string.Format("\r\nLog Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.",
                LogCount.ToString(),
                FileRwLockManage.WritedCount.ToString(),
                FileRwLockManage.FailedCount.ToString()));
        }

        #endregion

        #region Interlocked用法
        /*
            MSDN 描述：为多个线程共享的变量提供原子操作
            Interlocked.Increment　　　　原子操作，递增指定变量的值并存储结果。
            Interlocked.Decrement　　     原子操作，递减指定变量的值并存储结果。
            Interlocked.Add　　　　　　　 原子操作，添加两个整数并用两者的和替换第一个整数
            Interlocked.CompareExchange(ref a, b, c);  原子操作，a参数和c参数比较，  相等b替换a，不相等不替换。
        */
        static int Maxinum(ref int target, int value)
        {
            int currentVal = target, startVal, desiredVal;
            do
            {
                startVal = currentVal;
                desiredVal = Math.Max(startVal, value);
                //高并发下，线程抢占情况下，target值会发生改变。
                //target startVal相等说明没改变。desiredVal 直接替换。
                currentVal = Interlocked.CompareExchange(ref target, desiredVal, startVal);
            }
            while (startVal != currentVal);//不相等说明，target值已经被其他线程改动。自旋继续。
            return desiredVal;
        }

        const int numThreads = 10;
        static void InterlockExchange()
        {
            Thread myThread;
            Random rnd = new Random();
            for (int i = 0; i < numThreads; i++)
            {
                myThread = new Thread(new ThreadStart(InterlockManage.MyThreadProc));
                myThread.Name = string.Format("Thread{0}", i + 1);
                Thread.Sleep(rnd.Next(0, 1000));
                myThread.Start();
            }
        }

        static void InterLockIncAndDec()
        {
            //创建RptThread线程，每隔一秒通报有几个线程存在。
            Thread reporter = new Thread(new ThreadStart(InterIncAndDec.RptThread));
            reporter.IsBackground = true;
            reporter.Start();
            //创建50个rndThreads线程
            Thread[] rndThreads = new Thread[50];
            for (int i = 0; i < 50; i++)
            {
                rndThreads[i] = new Thread(new ThreadStart(InterIncAndDec.RndThreadFunc));
                rndThreads[i].Start();
            }
        }

        static void SpinInterLock()
        {
            Thread[] rndThreads = new Thread[5];
            for (int i = 0; i < 5; i++)
            {
                rndThreads[i] = new Thread(new ThreadStart(SpinLockProvider.RndThreadFunc));
                rndThreads[i].Start();
            }
        }

        #endregion

        #region 信号量使用

        static void SemaphoreApp()
        {
            Semaphore s = new Semaphore(0, 1024);
            Thread t1 = new Thread(new ParameterizedThreadStart(SemaphoreTest.ThreadOne));
            t1.IsBackground = true;
            t1.Start(s);
            Thread t2 = new Thread(new ParameterizedThreadStart(SemaphoreTest.ThreadTwo));
            t2.IsBackground = true;
            t2.Start(s);
        }

        static void DownloadFile()
        {
            //MultiDownLoad multi = new MultiDownLoad("code.pdf", "copy.pdf");
            MultiDownLoad multi = new MultiDownLoad("others.rar", "copy.rar");
            //MultiDownLoad multi = new MultiDownLoad("Orchard-dev.zip", "copy.zip");
            //MultiDownLoad multi = new MultiDownLoad("dnt.zip", "copy.zip");
            //MultiDownLoad multi = new MultiDownLoad("1203.pdm", "copy.pdm");
            //MultiDownLoad multi = new MultiDownLoad("VID.mp4", "copy.mp4");
            //MultiDownLoad multi = new MultiDownLoad("img.png", "copy.png");
            //MultiDownLoad multi = new MultiDownLoad(@"D:\software\SQLFULL_CHS.iso", "copy.iso");
            multi.Start();
        }

        #endregion

        #region 线程池
        /*
            参考来源地址：http://kb.cnblogs.com/page/42531/
         */
        static void ThreadPoolTest()
        {
            Console.WriteLine("Thread Pool Sample:");
            bool W2K = false;
            int MaxCount = 10;
            ManualResetEvent eventX = new ManualResetEvent(false);
            Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount);
            ThreadPoolApp tpa = new ThreadPoolApp(MaxCount);
            tpa.eventX = eventX;
            Console.WriteLine("Queue to Thread Pool 0");

            try
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(tpa.Beta), new SomeState(0));
                W2K = true;
            }
            catch (NotSupportedException)
            {
                W2K = false;
            }
            if (W2K)
            {
                for (int i = 1; i < MaxCount; i++)
                {
                    Console.WriteLine("Queue to Thread Pool {0}", i);
                    ThreadPool.QueueUserWorkItem(new WaitCallback(tpa.Beta), new SomeState(i));
                }
                Console.WriteLine("Waiting for Thread Pool to drain");
                eventX.WaitOne(Timeout.Infinite, true);
                //WaitOne()方法使调用它的线程等待直到eventX.Set()方法被调用
                Console.WriteLine("Thread Pool has been drained (Event fired)");
                foreach (object o in tpa.HashCount.Keys)
                {
                    Console.WriteLine("{0} {1}", o, tpa.HashCount[o]);
                }
            }
        }
        /*
            参考来源地址：http://www.2cto.com/kf/201410/344968.html
        */
        static void ThreadPoolSemphore()
        {
            ThreadPoolManager tpm = new ThreadPoolManager(2);
            TestTask t1 = new TestTask("task1");
            TestTask t2 = new TestTask("task2");
            TestTask t3 = new TestTask("task3");
            TestTask t4 = new TestTask("task4");
            TestTask t5 = new TestTask("task5");
            TestTask t6 = new TestTask("task6");
            TestTask t7 = new TestTask("task7");
            TestTask t8 = new TestTask("task8");
            TestTask t9 = new TestTask("task9");

            tpm.AddTask(t1);
            tpm.AddTask(t2);
            tpm.AddTask(t3);
            tpm.AddTask(t4);
            tpm.AddTask(t5);
            tpm.AddTask(t6);
            tpm.AddTask(t7);
            tpm.AddTask(t8);
            tpm.AddTask(t9);
        }
        #endregion

        #region 对象继承IDispose接口，实现对象垃圾回收

        static void ObjectDispose()
        {
            using (Factory f = new Factory())
            {
                f.MakeSomeGarbage();
                Console.WriteLine("Total memory is {0} KBs.", GC.GetTotalMemory(false) / 1024);
            }
            Console.WriteLine("After GC total memory is {0} KBs.", GC.GetTotalMemory(false) / 1024);
        }

        static void OjectGcCollection()
        {
            Console.WriteLine("Maxinum generations:" + GC.MaxGeneration);
            //在托管堆上创建一个新的GenObj对象
            object o = new GenObj();
            //刚刚创建，代龄为0
            Console.WriteLine("Gen " + GC.GetGeneration(o));
            //执行垃圾收集器，提高对象代龄
            GC.Collect();
            Console.WriteLine("Gen " + GC.GetGeneration(o));
            GC.Collect();
            Console.WriteLine("Gen " + GC.GetGeneration(o));
            GC.Collect();
            Console.WriteLine("Gen " + GC.GetGeneration(o));
            //销毁对象，此时对象的代龄为2
            o = null;
            Console.WriteLine("Collect Gen 0");
            //收集第0代对象，其实没有0代对象
            GC.Collect(0);
            GC.WaitForFullGCApproach();
            Console.WriteLine("Collect Gen 0");
            //收集第1代对象，其实没有1代对象
            GC.Collect(1);
            GC.WaitForFullGCApproach();
            Console.WriteLine("Collect Gen 0");
            //收集第2代对象，对象真正被收集
            GC.Collect(2);
            GC.WaitForFullGCApproach();//调用Finalize
        }

        #endregion

        #region AutoResetEvent使用

        static AutoResetEvent event_1 = new AutoResetEvent(true);
        static AutoResetEvent event_2 = new AutoResetEvent(false);
        static void AutoResetEventMethod()
        {
            Console.WriteLine("Press Enter to create three threads and start them.\r\n" +
                          "The threads wait on AutoResetEvent #1, which was created\r\n" +
                          "in the signaled state, so the first thread is released.\r\n" +
                          "This puts AutoResetEvent #1 into the unsignaled state.");
            Console.ReadLine();
            AutoResetEventManage autoEvent = new AutoResetEventManage(event_1, event_2);
            for (int i = 1; i < 4; i++)
            {
                Thread t = new Thread(autoEvent.ThreadProc);
                t.Name = string.Format("Thread_{0}", i.ToString());
                t.Start();
            }

            Thread.Sleep(250);
            for (int i = 0; i < 2; i++)
            {
                Console.WriteLine("Press Enter to release another thread.");
                Console.ReadLine();
                event_1.Set();
                Thread.Sleep(250);
            }

            Console.WriteLine("\r\nAll threads are now waiting on AutoResetEvent #2.");
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine("Press Enter to release a thread.");
                Console.ReadLine();
                event_2.Set();
                Thread.Sleep(250);
            }
        }

        #endregion

        #region ManualResetEvent使用

        static ManualResetEvent mre = new ManualResetEvent(false);
        static void ManualResetEventMethod()
        {
            ManualResetEventManage manualEventManage = new ManualResetEventManage(mre);
            Console.WriteLine("\nStart3 named threads that block on a ManualResetEvent:\n");
            for (int i = 0; i <= 2; i++)
            {
                Thread t = new Thread(manualEventManage.ThreadProc);
                t.Name = string.Format("Thread_{0}", i);
                t.Start();
            }
            Thread.Sleep(500);
            Console.WriteLine("\nWhen all three threads have started,press Enter to call Set()" + "\nto release all the threads.\n");
            Console.ReadLine();
            mre.Set();
            Thread.Sleep(500);
            Console.WriteLine("\nWhen a ManualResetEvent is signaled,threads that call WaitOne()" +
                "\ndo not block.Pree Enter to show this.\n");
            Console.ReadLine();
            for (int i = 3; i <= 4; i++)
            {
                Thread t = new Thread(manualEventManage.ThreadProc);
                t.Name = string.Format("Thread_{0}", i);
                t.Start();
            }
            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +
                          "\nwhen they call WaitOne().\n");
            Console.ReadLine();
            mre.Reset();

            Thread thread5 = new Thread(manualEventManage.ThreadProc);
            thread5.Name = "thread5";
            thread5.Start();

            Thread.Sleep(500);
            Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");
            Console.ReadLine();
            mre.Set();
        }

        static void MREMethod()
        {
            Console.WriteLine("****************************");
            Console.WriteLine("输入\"stop\"停止线程运行...");
            Console.WriteLine("输入\"run\"开启线程运行...");
            Console.WriteLine("****************************\r\n");
            MREDemo objMre = new MREDemo();
            objMre.CreateThreads();
            while (true)
            {
                string input = Console.ReadLine();
                if (input.Trim().ToLower() == "stop")
                {
                    Console.WriteLine("线程已停止运行...");
                    objMre.Reset();
                }
                else if (input.Trim().ToLower() == "run")
                {
                    Console.WriteLine("线程开启进行...");
                    objMre.Set();
                }
            }
        }
        #endregion
    }
}
